#include "block_queue.hpp"
#include "task.hpp"

BlockQueue<Task> bq;
pthread_mutex_t con_lock;
pthread_mutex_t pro_lock;

void* Produce(void*)
{
  pthread_mutex_lock(&pro_lock);
  char ops[] = "+-*/%";
  while(true){
    int x = rand() % 99 + 1;
    int y = rand() % 99 + 1;
    char op = ops[rand() % 5];
    Task t(x, y, op);
    bq.Push(t);
    usleep(200000);
  }

  pthread_mutex_unlock(&pro_lock);
}

void* Consume(void* arg)
{
  pthread_detach(pthread_self());
  long i = (long)arg;
  while(true){
    pthread_mutex_lock(&con_lock);
    Task t;
    bq.Pop(t);
    printf("thread[%ld]: ", i);
    t.Run();
    usleep(150000);
    pthread_mutex_unlock(&con_lock);
    usleep(100);
  }
}


int main(void)
{
  pthread_mutex_init(&pro_lock, nullptr);
  pthread_mutex_init(&con_lock, nullptr);

  srand((unsigned long)time(nullptr));
  pthread_t tds[5];
  //创建生产者线程
  for(int i = 0; i < 5; i++){
    pthread_create(&tds[i], nullptr, Produce, nullptr);
  }

  //创建消费者线程
  for(long i = 0; i < 5; i++){
    pthread_create(&tds[i], nullptr, Consume, (void*)i);
  }

  for(int i = 0; i < 5; i++){
    pthread_join(tds[i], nullptr); 
  }

  pthread_mutex_destroy(&pro_lock);
  pthread_mutex_destroy(&con_lock);
  return 0;
}
